# TorrentFetcher.py
#
# Copyright (c) 2006 Michael Hobbs
#
# This file is part of iTorrent.
#
# iTorrent is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# iTorrent is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with iTorrent; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA


import os
import time

from BitTorrent.bencode import bdecode
from BitTorrent.ConvertedMetainfo import ConvertedMetainfo

import utils
from KeepAlive import KeepAlive
from BTControl import LargestFileInfo


class TorrentFetcher(object):
	def __init__(self, btControl, feedStore):
		super(TorrentFetcher, self).__init__()
		self.btControl = btControl
		self.feedStore = feedStore
		self.activeTorrents = {}
		self.urlMap = {}

	def fetch(self, url, writer):
		# TODO: check for new version of torrent file if expired.
		record = self.feedStore[url]
		# TODO: download torrent file if not exists
		torrentFile = file(record.torrentFile, 'rb')
		data = torrentFile.read()
		torrentFile.close()
		largestInfo = LargestFileInfo(ConvertedMetainfo(bdecode(data)))
		keepAlive = KeepAlive(writer, largestInfo, self.btControl.display)
		pathName, torrent = self.btControl.getTorrent(data, url, self, keepAlive=keepAlive)
		self.activeTorrents[torrent] = (url, writer, pathName, None, None, None)
		self.urlMap[url] = torrent

	def finishedTorrent(self, torrent):
		url, writer, pathName, callback, args, kwargs = self.activeTorrents[torrent]
		self.feedStore[url].numFailures = 0
		# fetch() does not set callback, but prefetch() does.
		if callback:
			del self.activeTorrents[torrent]
			del self.urlMap[url]
			callback(pathName, *args, **kwargs)
			return True
		record = self.feedStore[url]
		record.sent = time.time()
		writer.close()
		return False

	def shutdownTorrent(self, torrent):
		url, writer, pathName, callback, args, kwargs = self.activeTorrents.pop(torrent)
		utils.remove(pathName)
		del self.urlMap[url]

	def failedTorrent(self, torrent):
		url, writer, pathName, callback, args, kwargs = self.activeTorrents.pop(torrent)
		self.feedStore[url].numFailures += 1
		if os.path.exists(pathName):
			utils.remove(pathName)
		del self.urlMap[url]
		if callback:
			callback(None, *args, **kwargs)
		if writer:
			writer.close()
		# end if

	def prefetch(self, url, callback, *args, **kwargs):
		record = self.feedStore[url]
		torrentFile = file(record.torrentFile, 'rb')
		data = torrentFile.read()
		torrentFile.close()
		largestInfo = LargestFileInfo(ConvertedMetainfo(bdecode(data)))
		pathName, torrent = self.btControl.getTorrent(data, url, self, [largestInfo.begin[0]], finishTimeout=300)
		self.activeTorrents[torrent] = (url, None, pathName, callback, args, kwargs)
		self.urlMap[url] = torrent

	def stop(self, url):
		torrent = self.urlMap.pop(url)
		self.btControl.stopTorrent(torrent)
